package com.seanliao.nav.util;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestAlgorithm;
import cn.hutool.crypto.digest.Digester;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;

/**
 * 密码工具类
 */
@Slf4j
@UtilityClass
public class PasswordUtil {
    /**
     * 摘要加密类型
     */
    private final DigestAlgorithm digestAlgorithm = DigestAlgorithm.MD5;

    /**
     * 加密算法加盐位置
     */
    private final int saltPosition = 1;

    /**
     * 生成盐长度
     */
    private final int saltLength = 32;

    /**
     * 字符串拼接盐插入位置
     */
    private final int saltInsertPosition = 16;

    /**
     * 加密
     * MD5+32位盐 拼接形成64位加密密码
     */
    public String encode(String password) {
        String salt = RandomUtil.randomString(saltLength);
        String digestPassword = new Digester(digestAlgorithm)
                .setSalt(salt.getBytes())
                .setSaltPosition(saltPosition)
                .digestHex(password);
        return insertSalt(digestPassword, salt);
    }

    /**
     * 匹配检查
     * true表示相同
     */
    public boolean match(String password, String encodePassword) {
        // 允许直接比较
        if (password.equals(encodePassword)){
            return true;
        }
        String salt = extractSalt(encodePassword);
        String digestPassword = new Digester(digestAlgorithm)
                .setSalt(salt.getBytes())
                .setSaltPosition(saltPosition)
                .digestHex(password);
        String saltPassword = insertSalt(digestPassword, salt);
        return encodePassword.equals(saltPassword);
    }


    /**
     * 插盐
     */
    public String insertSalt(String digestPassword, String salt) {
        String prefix = StrUtil.subPre(digestPassword, saltInsertPosition);
        String suffix = StrUtil.subSuf(digestPassword, saltInsertPosition);
        return StrUtil.strBuilder(prefix, salt, suffix).toString();
    }

    /**
     * 取盐
     */
    public String extractSalt(String saltPassword) {
        return StrUtil.subWithLength(saltPassword, saltInsertPosition, saltLength);
    }
}
